﻿package 
{

	import flash.events.Event;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.events.MouseEvent;
	import flash.display.MovieClip;
	import flash.external.ExternalInterface;
	import flash.system.Security;
	import flash.errors.IOError;
	import fl.events.SliderEvent;
	import flash.net.URLRequest;

	public class Audier extends MovieClip
	{
		private var array:Array = new Array;
		private var currentItem:int = 0;
		private var currentPosition:int = 0;
		public var isStarting:Boolean = false;
		public var playing:Boolean = false;
		private var sound:Sound = new Sound;
		private var soundChannel:SoundChannel = new SoundChannel;
		
		public function Audier()
		{
			Security.allowDomain("*");
			ExternalInterface.marshallExceptions = true;
			this.addCallBacks();
			
			btnPlayPause.addEventListener(MouseEvent.CLICK, onClickPlayPause);
			sldTime.addEventListener(SliderEvent.CHANGE, onChangeSlider);
			
			//playSound(simpleString());
			
			alertArray(array);
		}
		
		/** Play mot doan van duoc chuyen vao boi tham so paragraph
		 *  Cach thuc: play tung cau trong doan van, moi cau se tao mot doi tuong Sound moi
		 *  nhung luon duy tri doi tuong SoundChannel hien tai de xu li viec pause va resume
		 */
		private function playSound(paragraph:String):void{
			txtJS.text = paragraph;   // hien thi paragraph len TextField de kiem tra javascript co truyen duoc hay khong
			array = splitParagraph(paragraph);
			if(array.length == 0) return;
			currentItem = 0;
			currentPosition = 0;
			isStarting = true;
			playing = true;
			try{
				if(sound){ soundChannel.stop(); sound.close(); }
			}catch(error:IOError){
				txtStatus.text = "Loi IO : khong close duoc sound" + error;
			}
			
			try{
				sound = new Sound;
				sound.load(new URLRequest("http://translate.google.com.vn/translate_tts?tl=en&q="+array[currentItem]));
				soundChannel = sound.play();
				soundChannel.addEventListener(Event.SOUND_COMPLETE, onPlayBackComplete);
				txtStatus.text = "Phat cau thu " + currentItem;
			}catch(error:IOError){
				txtStatus.text = "Loi IO: "+error.message;
			}catch(error:SecurityError){
				txtStatus.text = "Loi Security:"+error.message;
			}
		}
		
		/** Khi ket thuc mot cau, ta chay cau tiep theo.
		 *  Neu cau cuoi chay xong,bao hieu ket thuc isStarting = false;
		 *  Neu bi Error khi load mot cau nao do, thi se dung phat toan bo doan van
		 */
		private function onPlayBackComplete(event:Event){
			currentItem = currentItem+1;
			if(currentItem == array.length){
				isStarting = false;
				return;
			}
			
			// phát câu hiện tại
			playCurrent();
		}
		
		/** Phuong thuc cho phep tua doan van.
		 *  Co che : Dua vao phan tram nguoi dung keo slider, ta tinh tuong doi xem nen phat tiep cau nao.
		 */
		private function onChangeSlider(event:SliderEvent){
			currentItem = int((event.target.value/event.target.maximum)*(array.length-1));
			try{
				if(sound){ soundChannel.stop(); sound.close();}
			}catch(error:IOError){
				txtStatus.text = "Loi IO khong close duoc sound torng ham onChangeSlider";
			}
			
			// chay item hien tai
			playCurrent();
		}
		
		/** Thuc hien dừng phát câu hiện tại và nhảy sang câu tiếp theo
		 */
		private function next(){
			// chuyển sang câu tiếp theo, nếu qua câu cuối, dừng lại ngay
			currentItem = currentItem+1;
			if(currentItem >= array.length){
				isStarting = false;
				return;
			}
			
			// Hiện tại đang phát dở thì dừng lại 
			try{
				if(sound){ soundChannel.stop(); sound.close();}
			}catch(error:IOError){
				txtStatus.text = "Loi IO khong close duoc sound torng ham onChangeSlider";
			}
			
			// Sau khi dừng câu đang phát dở lại thì load và phát câu vừa chuyển
			playCurrent();
		}
		
		private function playCurrent():void{
			try{
				sound = new Sound;
				isStarting = true;
				sound.load(new URLRequest("http://translate.google.com.vn/translate_tts?tl=en&q="+array[currentItem]));
				soundChannel = sound.play();
				if(!playing){
					currentPosition = soundChannel.position;
					soundChannel.stop();
				}
				soundChannel.addEventListener(Event.SOUND_COMPLETE, onPlayBackComplete);
				sldTime.value = int((currentItem/(array.length-1))*sldTime.maximum);
				txtStatus.text = "phat cau thu "+currentItem;
			}catch(error:IOError){
				txtStatus.text = "Loi IO: "+error.message;
			}catch(error:SecurityError){
				txtStatus.text = "Loi Security:"+error.message;
			}
		}
		
		/** Xet trong qua trinh chay ca doan van, nguoi dung an pause thi luu lai vi tri va pause
		 *  nguoi dung an play thi chay lai vi tri do
		 *  Co che : Kiem soat play/pause thong qua tham chieu soundChannel va thuoc tinh playing
		 */
		private function onClickPlayPause(event:MouseEvent){
			playPause();
		}
		
		private function playPause(){
			if(isStarting){
				if(playing){
					currentPosition = soundChannel.position;
					soundChannel.stop();
					playing = false;
					btnPlayPause.label = "play";
				}else{
					soundChannel = sound.play(currentPosition);
					soundChannel.addEventListener(Event.SOUND_COMPLETE, onPlayBackComplete);
					playing = true;
					btnPlayPause.label = "pause";
				}
			}
		}
		
		
		
		private function addCallBacks():void{
			if(ExternalInterface.available){
				try{
					ExternalInterface.addCallback("sendToFlash", playSound);
					ExternalInterface.addCallback("next", next);
					ExternalInterface.addCallback("pause", playPause);
					ExternalInterface.addCallback("resume", playPause);
					txtStatus.text = "ExternalInterface available";
				}catch(e:Error){
					txtStatus.text = "Loi khi nhan message tu JS"+e.errorID;
				}
			}else{
				txtStatus.text = "ExternalInterface not avaiable";
			}
		}
		
		
		
		/** Chia doan van dai thanh cac cau ngan
		 *  return : Doi tuong Array chua cac cau ngan
		 */
		private function splitParagraph(text:String):Array{
			var textResult = new Array();
			var reg:RegExp = /[.!?:;()“”]/g ;   // Cac dau phan cach cau
			var textArr = text.split(reg); // Tach doan van thanh cac cau, luu vao mang textArr
			
			// Duyet mang cac cau thu duoc, cau nao dai phai tach tiep thanh cac cau ngan hon 90 ki tu
			var i = 0;
			for(i = 0; i < textArr.length; i++){
				// chuan hoa str truoc: loai bo whitespace truoc va sau cau
				var str = trim(textArr[i]);
				
				// Phan tich chuoi
				if(str.length == 0){
					// do nothing with str
				}else if(str.length > 0 && str.length <= 100){
					textResult.push(str);
				} else if(str.length > 100){ // tach str thanh nhieu doan ma kich thuoc nho hon 100 ki tu
					textResult = textResult.concat(splitLongStr(str));
				}
			}
			
			return textResult;
		}
		
		/** Chuan hoa co ban chuoi str. */
		private function trim(str:String):String{
			var ltrimpatt:RegExp = /^\s*/g;
			var rtrimpatt = /\s*$/g;
			str = str.replace(ltrimpatt,'');
			str = str.replace(rtrimpatt,'');
			return str;
		}
		
		/** Ham tach mot cau dai thanh nhieu doan sao cho dam bao ngu phap khong bi tach tu. */
		private function splitLongStr(str:String):Array{
			var result = new Array();
			while(str.length > 100){
				var i:int=100;
				while(str.charAt(i) != ' ') i--;
				var token:String = str.substring(0,i);
				result.push(token);
				str = str.substring(i+1);
			}
			result.push(str);
			return result;
		}
		
		private function alertArray(array:Array):void{
			var str = new String("");
			var i:int = 0;
			for(i = 0; i < array.length; i++){
				str += "array["+i+"]="+array[i]+"\n";
			}
			trace(str);
		}
		
		private function simpleString():String{
			var str:String = "German Chancellor Angela Merkel told Greece the sacrifices it makes toward cutting spending will pay off, an unpopular message to tens of thousands who protested her visit to the country.";
				str += "Merkel made her remarks after meeting Tuesday with conservative Greek Prime Minister Antonis Samaras in Athens.  Her five-hour stop in Greece was her first visit to the country since the eurozone crisis began several years ago.";
				str += "Thousands of police were spread throughout the capital to control more than 25,000 protesters.  Police briefly clashed with some demonstrators and detained at least 40 people.";
			return str;
		}
	}


}